package logic

import (
	"context"
	"encoding/xml"
	"fmt"

	"laundry-service/app/client/internal/svc"
	"laundry-service/app/client/internal/types"
	"laundry-service/entity"

	"github.com/zeromicro/go-zero/core/logx"
)

type OrderStNtfCallbackLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

const (
	StatusDispatchFailed  = "04"            
	StatusDispatchSuccess = "04-40001"      
	StatusOrderReceived   = "04-40037"      
	StatusDispatchCancel  = "00-40045-1000" 
)

const (
	StatusCustomerCancel = "00-2000"        
	StatusOrderMistake   = "04-40002-40016" 
	StatusOrderDuplicate = "04-40002-40015" 
)

const (
	StatusTimeoutWithAction    = "04-40002-40065" 
	StatusTimeoutWithoutAction = "00-40065"       
)


const (
	StatusPhoneError             = "04-40002-40021" 
	StatusCannotAccessCustomer   = "04-40002-40022" 
	StatusContactFailed          = "04-40002-40004" 
	StatusChangePickupTime       = "04-40002-40005" 
	StatusWeatherDelay           = "04-40002-40027" 
	StatusTrafficDelay           = "04-40002-40028" 
	StatusExcessiveWorkload      = "04-40002-40035" 
	StatusNotMeetPickupCondition = "04-40002-40031" 
)

const (
	StatusHeavyTransfer = "04-40002-40036" // 重货需转单
)

const (
	StatusNormalPickup = "05-40003" // 正常收件
)

func NewOrderStNtfCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderStNtfCallbackLogic {
	return &OrderStNtfCallbackLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *OrderStNtfCallbackLogic) OrderStNtfCallback(req *types.WkStNtfReq) (resp []byte, err error) {
	var orderStNtfReq entity.OrderStNtfReq
	bin, _ := xml.MarshalIndent(&SFReply{Head: "OK"}, "", "  ")

	if err := xml.Unmarshal([]byte(req.Pkg), &orderStNtfReq); err != nil {
		fmt.Printf("xml.Unmarshal error: %v\n", err)
	}

	order, orderErr := l.svcCtx.Db.GetOrderBySFBillCode(orderStNtfReq.WaybillNo)
	if orderErr != nil {
		logx.Errorf("查询订单失败，请求体参数: %v, 错误: %v", orderStNtfReq, err)
	}
	expressBind, bindErr := l.svcCtx.Db.GetExpressBindBySFBillCode(orderStNtfReq.WaybillNo)
	if bindErr != nil {
		logx.Errorf("查询绑定失败，请求体参数: %v, 错误: %v", orderStNtfReq, err)
	} else {
		order, orderErr = l.svcCtx.Db.GetOrderByExpOrderCode(expressBind.FirstCustomOrderCode)
		if orderErr != nil {
			logx.Errorf("根据绑定记录中的第一程运单号查询订单失败: %v, 错误: %v", orderStNtfReq, err)
		}
	}

	if orderErr != nil && bindErr != nil {
		return bin, err
	}

	expressLog := new(entity.ExpressLog)
	if orderErr != nil {
		expressLog.OrderId = expressBind.OrderId
	} else {
		expressLog.OrderId = uint(order.ID)
	}

	expressLog.OrderNo = orderStNtfReq.OrderNo
	expressLog.CustOrderCode = orderStNtfReq.CustOrderCode
	expressLog.WaybillNo = orderStNtfReq.WaybillNo
	expressLog.OrderStateCode = orderStNtfReq.OrderStateCode
	expressLog.OrderStateDesc = orderStNtfReq.OrderStateDesc
	expressLog.EmpCode = orderStNtfReq.EmpCode
	expressLog.EmpPhone = orderStNtfReq.EmpPhone
	expressLog.NetCode = orderStNtfReq.NetCode
	expressLog.LastTime = orderStNtfReq.LastTime
	expressLog.BookTime = orderStNtfReq.BookTime
	expressLog.CarrierCode = orderStNtfReq.CarrierCode
	if err := l.svcCtx.Db.SaveExpressLog(expressLog); err != nil {
		logx.Errorf("保存顺丰推送失败，运单号: %s, 错误: %v", orderStNtfReq.CustOrderCode, err)
		return nil, nil
	}

	statusCode := orderStNtfReq.OrderStateCode

	switch orderStNtfReq.OrderStateCode {
	case StatusDispatchFailed, StatusDispatchCancel:
		l.handleDispatchIssues(statusCode, order)
	case StatusDispatchSuccess, StatusOrderReceived:
		l.handleDispatchSuccess(statusCode, order)
	case StatusCustomerCancel, StatusOrderMistake, StatusOrderDuplicate:
		l.handleOrderCancellation(statusCode, order)
	case StatusTimeoutWithAction, StatusTimeoutWithoutAction:
		l.handleTimeoutOrder(statusCode, order)
	case StatusPhoneError, StatusCannotAccessCustomer, StatusContactFailed,
		StatusChangePickupTime, StatusWeatherDelay, StatusTrafficDelay,
		StatusExcessiveWorkload, StatusNotMeetPickupCondition:
		handlePickupException(statusCode)
	case StatusHeavyTransfer:
		handleLogisticsException(statusCode)
	case StatusNormalPickup:
		handleNormalPickup(statusCode, order)
	default:
		fmt.Println("未知状态码:", statusCode)
	}
	err = l.svcCtx.Db.SaveOrder(order)
	if err != nil {
		logx.Errorf("保存订单失败，订单ID: %d, 错误: %v", order.ID, err)
	}

	return bin, nil
}

// 调度相关问题处理
func (l *OrderStNtfCallbackLogic) handleDispatchIssues(statusCode string, order *entity.Order) {
	fmt.Println("处理调度问题，状态码:", statusCode)

	// 调度取消
	if statusCode == StatusDispatchCancel {
		order.State = -1
		l.refundProcess(order)
	}
}

// 处理调度成功
func (l *OrderStNtfCallbackLogic) handleDispatchSuccess(statusCode string, order *entity.Order) {
	fmt.Println("处理调度成功，状态码:", statusCode)
	// 订单已接收
	if statusCode == StatusOrderReceived {
		reservationOrder, err := l.svcCtx.Db.FindReservationOrderByOrderId(order.ID)
		if err != nil {
			logx.Errorf("查询预约订单失败，订单ID: %d, 错误: %v", order.ID, err)
			return
		}

		reservationOrder.IsActivated = true
		if err := l.svcCtx.Db.SaveReservationOrder(reservationOrder); err != nil {
			logx.Errorf("更新预约订单顺丰接收状态失败，订单ID: %d, 错误: %v", order.ID, err)
			return
		}
	}
}


func (l *OrderStNtfCallbackLogic) handleOrderCancellation(statusCode string, order *entity.Order) {
	fmt.Println("处理订单取消，状态码:", statusCode)
	order.State = -1
	l.refundProcess(order)
}


func (l *OrderStNtfCallbackLogic) handleTimeoutOrder(statusCode string, order *entity.Order) {
	fmt.Println("处理超时消单，状态码:", statusCode)
	order.State = -2
	// 进入退款流程
	l.refundProcess(order)
}


func handlePickupException(statusCode string) {
	fmt.Println("处理收派异常，状态码:", statusCode)
}


func handleLogisticsException(statusCode string) {
	fmt.Println("处理物流异常，状态码:", statusCode)
}


func handleNormalPickup(statusCode string, order *entity.Order) {
	order.State = 3
	fmt.Println("处理正常收件，状态码:", statusCode)
}


func (l *OrderStNtfCallbackLogic) refundProcess(order *entity.Order) {
	reservationOrder, err := l.svcCtx.Db.FindReservationOrderByOrderId(order.ID)
	if err != nil {
		logx.Errorf("查询预约订单失败，订单ID: %d, 错误: %v", order.ID, err)
		return
	}

	if reservationOrder.IsActivated {
		logx.Errorf("订单已激活，无法退款，订单ID: %d", order.ID)
		return
	}

	t, e := CreateRefundTokenByOrder(l.svcCtx.Db, order)
	if e != nil {
		logx.Errorf("创建退款记录失败，订单ID: %d, 错误: %v", order.ID, e)
		return
	}

	l.WXRefundFunc(order, t)
}

func (l *OrderStNtfCallbackLogic) WXRefundFunc(order *entity.Order, t *entity.OrderRefund) {
	resp, err := WxRefoundRequest(l.ctx, *l.svcCtx, order.Number, t.RefundNo, order.RealAmount)
	if err != nil {
		t.Status = "ABNORMAL"
		order.State = -1

		log := new(entity.OrderLog)
		log.OrderId = order.ID
		log.State = -3
		log.Remark = "微信退款失败"
		log.Attr = fmt.Sprintf("%v", err)

		err = l.svcCtx.Db.TxRefund(order, t, log)
		if err != nil {
			logx.Errorf("退款失败，订单ID: %d, 错误: %v", order.ID, err)
			return
		}
		return
	}

	wxRefundLog := entity.NewStateLogWithOrder(order, -1, "微信退款中", "")
	t.Status = "PROCESSING"

	wxRefundLog.Remark = "申请微信退款"
	wxRefundLog.Attr = string(resp)
	_ = FinishRefundByWxResponse(*l.svcCtx, resp)
}
